
package com.task.base;

import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
import android.content.pm.*;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.io.*;
import java.lang.reflect.Method;
import java.util.List;
import java.util.StringTokenizer;
import java.util.concurrent.CountDownLatch;

public class Util {

    /**
     * 释放内存的action
     */
    public static final String ACTION_FREE_MEMORY = "com.ztemt.task.action.FREE_MEMORY";

    /**
     * 获取列表对话框。
     * 
     * @param context
     * @param title
     * @param itemsId 列表内容IDs
     * @return
     */
    public static Dialog getListDialog(final Context context, final int itemsId, View view) {
        return new AlertDialog.Builder(context).setCustomTitle(view)
                .setItems(itemsId, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {

                        String[] items = context.getResources().getStringArray(itemsId);
                        new AlertDialog.Builder(context).setMessage(
                                "You selected: " + which + " , " + items[which]).show();
                    }
                }).create();
    }

    /**
     * 获取列表对话框。
     * 
     * @param context
     * @param title
     * @param itemsId 列表内容IDs
     * @return
     */
    public static Dialog getListDialog(final Context context, String title, final int itemsId,
            Drawable icon, final IlistDialogClick dealWith, final ProcessItem item) {
        return new AlertDialog.Builder(context).setIcon(icon).setTitle(title)
                .setItems(itemsId, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        if (dealWith != null) {
                            dealWith.dealWith(which, item);
                        }
                    }
                }).create();
    }

    /**
     * 获取确认对话框.
     * 
     * @param context
     * @param title
     * @param icon
     * @return
     */
    public static Dialog getOkCancelDialog(final Context context, String title, Drawable icon) {
        return new AlertDialog.Builder(context)
                .setIcon(icon)
                .setTitle(title)
                .setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {

                        /* User clicked OK so do some stuff */
                    }
                })
                .setNegativeButton(R.string.alert_dialog_cancel,
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {

                                /* User clicked Cancel so do some stuff */
                            }
                        }).create();
    }

    /**
     * 获取SD卡信息
     * 
     * @param context
     * @return 数组第一个是所有sd卡空间，第二个是可用空间。
     */
    public static String[] getSdInfo(Context ctx) {
        // linux把设备当作文件处理,从系统中获取SD设备
        File path = Environment.getExternalStorageDirectory();
        // 新建一个stat，它可以查看路径上面的系统文件
        StatFs stat = new StatFs(path.getPath());
        // 一个块的 有多少字节
        long blockSize = stat.getBlockSize();
        // 设备上有多少个空闲的块
        long availableBlock = stat.getAvailableBlocks();
        // 设备上所有的块
        long allBlock = stat.getBlockCount();
        Log.v("tag", String.valueOf(blockSize));
        Log.v("tag", String.valueOf(allBlock));
        // 换算成字节
        long availablePlace = availableBlock * blockSize;// 空闲的
        long all = allBlock * blockSize;// 所有的
        // 换算成GB 或 MB单位
        String[] data = {
                formatSize(all, ctx), formatSize(availablePlace, ctx)
        };
        return data;
    }

    /**
     * 获取手机内部存储信息
     * 
     * @param context
     * @return 
     *         返回字符串数组，数组长度为3，第一个为可用容量(带有单位，不能转为数字)，第二个为总容量(带有单位，不能转为数字)，第三个为使用率(
     *         可转为float类型)
     */
    public static String[] getStorageInfo(Context context) {

        String[] data = new String[3];
        StatFs stat = new StatFs(Environment.getDataDirectory().getPath());

        long bytesAvailable = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();

        long byteTotal = (long) stat.getBlockCount() * (long) stat.getBlockSize();

        data[0] = Formatter.formatFileSize(context, bytesAvailable);
        data[1] = Formatter.formatFileSize(context, byteTotal);
        data[2] = (float) (byteTotal - bytesAvailable) / (float) byteTotal + "";

        return data;
    }

    /**
     * 格式化数据。
     * 
     * @param size 单位是byte
     * @param ctx
     * @return
     */
    public static String formatSize(long size, Context ctx) {
        if (size == -1) {
            return ctx.getString(R.string.info_not_available);
        } else {
            return Formatter.formatFileSize(ctx, size);
        }
    }

    /**
     * 获取内存信息
     * 
     * @param context
     * @return 
     *         返回字符串数组，数组长度为3，第一个为可用容量(带有单位，不能转为数字)，第二个为总容量(带有单位，不能转为数字)，第三个为使用率(
     *         可转为float类型)
     */
    public static String[] getMemoryInfo(Context context) {
        String[] info = new String[3];
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        MemoryInfo memoryInfo = new MemoryInfo();
        am.getMemoryInfo(memoryInfo);
        long availMem = memoryInfo.availMem;
        info[0] = Formatter.formatFileSize(context, availMem);

        String str1 = "/proc/meminfo";// 系统内存信息文件
        String str2;
        String[] arrayOfString;
        long totalMem = 0;

        try {
            FileReader localFileReader = new FileReader(str1);
            BufferedReader localBufferedReader = new BufferedReader(localFileReader, 8192);
            str2 = localBufferedReader.readLine();// 读取meminfo第一行，系统总内存大小

            arrayOfString = str2.split("\\s+");
            for (String num : arrayOfString) {
                Log.i(str2, num + "\t");
            }

            totalMem = Integer.valueOf(arrayOfString[1]).intValue() * 1024;// 获得系统总内存，单位是KB，乘以1024转换为Byte
            localBufferedReader.close();
            info[1] = Formatter.formatFileSize(context, totalMem);

        } catch (IOException e) {
        }

        info[2] = (float) (totalMem - availMem) / (float) totalMem + "";
        return info;
    }

    /**
     * 读取cpu的 工作时间和空闲时间。
     * 
     * @return [worktime, idletime]
     */
    public static long[] readCpuLoad() {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/stat")), //$NON-NLS-1$
                    256);

            String line = reader.readLine();

            if (line != null && line.startsWith("cpu ")) //$NON-NLS-1$
            {
                line = line.substring(3).trim();

                StringTokenizer tokens = new StringTokenizer(line);

                long totaltime = 0, idletime = 0;
                int i = 0;
                String tk;

                while (tokens.hasMoreTokens() && i < 7) {
                    tk = tokens.nextToken();

                    if (i == 3) {
                        idletime = Long.parseLong(tk);
                    } else {
                        totaltime += Long.parseLong(tk);
                    }
                    i++;
                }

                return new long[] {
                        totaltime, idletime
                };
            }
        } catch (Exception e) {
            Log.e(TAG, e.getLocalizedMessage(), e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    Log.e(TAG, e.getLocalizedMessage(), e);
                }
            }
        }

        return null;
    }

    public static void readProcessStat(Context ctx, byte[] buf, ProcessItem pi) {
        InputStream is = null;
        try {
            is = new FileInputStream("/proc/" //$NON-NLS-1$
                    + pi.pid + "/stat"); //$NON-NLS-1$

            ByteArrayOutputStream output = new ByteArrayOutputStream();

            int len;

            while ((len = is.read(buf)) != -1) {
                output.write(buf, 0, len);
            }

            output.close();

            String line = output.toString();

            if (line != null) {
                line = line.trim();

                int idx = line.lastIndexOf(')');

                if (idx != -1) {
                    line = line.substring(idx + 1).trim();

                    StringTokenizer tokens = new StringTokenizer(line);

                    String rss = null;
                    String utime = null;
                    String stime = null;

                    long nrss;
                    int i = 0;
                    String tk;

                    // [11,12,21] for [utime,stime,rss]
                    while (tokens.hasMoreTokens()) {
                        tk = tokens.nextToken();

                        if (i == 11) {
                            utime = tk;
                        } else if (i == 12) {
                            stime = tk;
                        } else if (i == 21) {
                            rss = tk;
                        }

                        if (rss != null) {
                            break;
                        }

                        i++;
                    }

                    if (utime != null) {
                        pi.cputime = Long.parseLong(utime);
                    }

                    if (stime != null) {
                        pi.cputime += Long.parseLong(stime);
                    }

                    if (rss != null) {
                        nrss = Long.parseLong(rss);

                        if (pi.rss != nrss || pi.mem == null) {
                            pi.rss = nrss;
                            pi.memValue = pi.rss * 4 * 1024;
                            pi.mem = Formatter.formatFileSize(ctx, pi.memValue);
                        }
                    }
                }
            }
        } catch (Exception e) {
            Log.e(TAG, e.getLocalizedMessage(), e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    Log.e(TAG, e.getLocalizedMessage(), e);
                }
            }
        }
    }

    /**
     * @return [State, UID, GID, Threads]
     */
    private static String[] readProcStatus(int pid) {
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/" //$NON-NLS-1$
                    + pid + "/status")), //$NON-NLS-1$
                    1024);

            String line;
            String stateMsg = ""; //$NON-NLS-1$
            String uidMsg = ""; //$NON-NLS-1$
            String gidMsg = ""; //$NON-NLS-1$
            String threadsMsg = ""; //$NON-NLS-1$

            while ((line = reader.readLine()) != null) {
                if (line.startsWith("State:")) //$NON-NLS-1$
                {
                    if (line.length() > 6) {
                        stateMsg = line.substring(6).trim();
                    }
                } else if (line.startsWith("Uid:")) //$NON-NLS-1$
                {
                    if (line.length() > 4) {
                        uidMsg = line.substring(4).trim();

                        int idx = uidMsg.indexOf('\t');
                        if (idx != -1) {
                            uidMsg = uidMsg.substring(0, idx);
                        } else {
                            idx = uidMsg.indexOf(' ');
                            if (idx != -1) {
                                uidMsg = uidMsg.substring(0, idx);
                            }
                        }
                    }
                } else if (line.startsWith("Gid:")) //$NON-NLS-1$
                {
                    if (line.length() > 4) {
                        gidMsg = line.substring(4).trim();

                        int idx = gidMsg.indexOf('\t');
                        if (idx != -1) {
                            gidMsg = gidMsg.substring(0, idx);
                        } else {
                            idx = gidMsg.indexOf(' ');
                            if (idx != -1) {
                                gidMsg = gidMsg.substring(0, idx);
                            }
                        }
                    }
                } else if (line.startsWith("Threads:")) //$NON-NLS-1$
                {
                    if (line.length() > 8) {
                        threadsMsg = line.substring(8).trim();
                    }
                }
            }

            return new String[] {
                    stateMsg, uidMsg, gidMsg, threadsMsg
            };
        } catch (Exception e) {
            Log.e(TAG, e.getLocalizedMessage(), e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException ie) {
                    Log.e(TAG, ie.getLocalizedMessage(), ie);
                }
            }
        }

        return null;
    }

    /**
     * 一键释放内存
     * 
     * @param context
     */
    public static Float freeMemory(Context context) {
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        MemoryUseInfo info = new MemoryUseInfo();
        info.exeFree(am);
        Float beginFree = Float.parseFloat(info.free);

        killAllProcess(context);

        info.exeFree(am);
        Float newFree = Float.parseFloat(info.free);
        Float release = new Float(newFree / 1024) - new Float(beginFree / 1024);
        return release > 0 ? release : 0;
    }

    /**
     * 杀死所有进程
     * 
     * @param context
     */
    public static void killAllProcess(Context context) {
        try {
            ActivityManager am = (ActivityManager) context
                    .getSystemService(Context.ACTIVITY_SERVICE);
            List<RunningAppProcessInfo> raps = am.getRunningAppProcesses();
            if (raps == null) {
                return;
            }

            String self = context.getPackageName();

            String name;

            for (int i = 0, size = raps.size(); i < size; i++) {
                RunningAppProcessInfo rap = raps.get(i);

                name = rap.processName;
                if (name.equals(self) || Util.isSystemApplication(name)) {
                    continue;
                }

                if (rap.pkgList != null) {
                    for (String pkg : rap.pkgList) {
                        if (pkg != null) {
                            am.restartPackage(pkg);
                            // am.forceStopPackage(pkg);//强制关闭，用于中兴手机
                        }
                    }
                }
                // am.restartPackage(name);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return;
    }

    /**
     * 判断是否系统程序。
     * 
     * @param packageName
     * @return
     */
    public static boolean isSystemApplication(String packageName) {
        if (packageName == null) {
            return false;
        }
        if (packageName.startsWith("com.google.process")
                || packageName.startsWith("com.android.phone")
                || packageName.startsWith("android.process")
                || packageName.startsWith("system")
                || packageName.startsWith("com.android.inputmethod")
                || packageName.startsWith("com.android.alarmclock")
                || packageName.startsWith("com.android.launcher")
                || packageName.startsWith("com.nuance.xt9.input")// 中兴内置输入法
                || packageName.startsWith("com.android.systemui")
                || packageName.startsWith("com.android.magicsmoke")
                || packageName.startsWith("com.google.android")) {
            return true;
        } else {
            return false;
        }
    }

    private static List<ResolveInfo> infoList = null;

    public static synchronized List<ResolveInfo> getRunableList(PackageManager pm, boolean reload) {
        if (infoList == null || reload == true) {
            Intent baseIntent = new Intent(Intent.ACTION_MAIN);
            baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
            infoList = pm.queryIntentActivities(baseIntent, 0);
        }
        return infoList;
    }

    /**
     * 根据包名返回可运行的intent
     * 
     * @param packageName
     * @param pm
     * @return
     */
    public static Intent getIntent(String packageName, PackageManager pm) {
        List<ResolveInfo> list = getRunableList(pm, false);
        for (ResolveInfo info : list) {
            if (packageName.equals(info.activityInfo.packageName)) {
                Intent i = new Intent(Intent.ACTION_MAIN);
                i.addCategory(Intent.CATEGORY_LAUNCHER);
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                i.setClassName(packageName, info.activityInfo.name);
                return i;
            }
        }
        return null;
    }

    /**
     * 运行指定的程序
     * 
     * @param packageName 程序的包名
     * @param pm
     * @param context
     */
    public static void runApplication(String packageName, PackageManager pm, Context context) {
        Intent intent = getIntent(packageName, pm);
        if (intent != null) {
            context.startActivity(intent);
        } else {
            Toast.makeText(context, R.string.message_switch_fail, Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 跳转到程序详情页面
     * 
     * @param packageName
     * @param context
     */
    public static void runApplicationDetails(String packageName, Context context) {

        Intent intent = new Intent();
        final int apiLevel = Build.VERSION.SDK_INT;
        if (apiLevel >= 9) { // 2.3（ApiLevel 9）以上，使用SDK提供的接口
            intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
            Uri uri = Uri.fromParts("package", packageName, null);
            intent.setData(uri);
        } else {
            // 2.3以下，使用非公开的接口（查看InstalledAppDetails源码）
            // 2.2和2.1中，InstalledAppDetails使用的APP_PKG_NAME不同。
            final String appPkgName = (apiLevel == 8 ? "pkg"
                    : "com.android.settings.ApplicationPkgName");
            intent.setAction(Intent.ACTION_VIEW);
            intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
            intent.putExtra(appPkgName, packageName);
        }
        context.startActivity(intent);
    }

    /**
     * 卸载指定程序
     * 
     * @param packageName 程序的包名
     * @param context
     */
    public static void unintallApplication(String packageName, Context context) {
        Uri uri = Uri.parse("package:" + packageName);
        Intent deleteIntent = new Intent(Intent.ACTION_DELETE, uri);
        context.startActivity(deleteIntent);
    }

    public static void killProcess(String packageName, ActivityManager am, Context context) {
    	System.out.println("kill process name is"+packageName);
        if (packageName.equalsIgnoreCase("system")) {
            return;
        }
        if (packageName.equals(context.getPackageName())) {
            return;
        }
        am.restartPackage(packageName);
        // am.forceStopPackage(packageName);//强制关闭，用于中兴手机
    }

    /**
     * 读取应用程序占用空间(只是显示一位小数)。
     * 这种通过反射调用系统隐藏方法(经过评审要求使用下面计算方法而不使用计算APK方法)，在升级的时候需要测试验证。
     * 
     * @param appInfo
     * @return
     */
    public static String getAppContainSize(ApplicationInfo appInfo, Context context,
            PackageManager pm) {
        String size = "0KB";
        MySizeObserver mySizeObserver = new MySizeObserver(pm);
        if (mySizeObserver != null) {
            CountDownLatch count = new CountDownLatch(1);
            String packageName = appInfo.packageName;
            mySizeObserver.invokeGetSize(packageName, count);
            try {
                count.await();
            } catch (InterruptedException e) {
                Log.i("AppManager", "Failed computing size for pkg : " + packageName);
            }
            // Process the package statistics
            PackageStats pStats = mySizeObserver.stats;
            boolean succeeded = mySizeObserver.succeeded;
            long total;
            if (succeeded && pStats != null) {
                total = getTotalSize(pStats);
            } else {
                total = -1;
            }

            if (total != -1) {
                size = Formatter.formatFileSize(context, total);
            }

        }

        return size;
    }

    /**
     * 用来动态计算应用程序大小的内部类。
     * 
     * @author Administrator
     */
    private static class MySizeObserver extends IPackageStatsObserver.Stub {
        private CountDownLatch mCount;

        private PackageManager myMPm;

        PackageStats stats;

        boolean succeeded;

        Method getPackageSizeInfo;

        public MySizeObserver(PackageManager currentmPm) {
            myMPm = currentmPm;
            try {
                getPackageSizeInfo = myMPm.getClass().getMethod("getPackageSizeInfo", String.class,
                        IPackageStatsObserver.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void invokeGetSize(String packageName, CountDownLatch count) {
            mCount = count;
            try {
                getPackageSizeInfo.invoke(myMPm, packageName, this);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onGetStatsCompleted(PackageStats pStats, boolean pSucceeded) {
            succeeded = pSucceeded;
            stats = pStats;
            mCount.countDown();
        }
    }

    public static void addShortcut(final Context context) {

        // 创建一个默认的Intent
        Intent shortcut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");

        // 快捷方式的名称
        shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.shortcut_title));
        // 不允许重复创建
        shortcut.putExtra("duplicate", false);

        Intent intent = new Intent(context.getApplicationContext(), ShortcutActivity.class);
        intent.putExtra("onekey", true);
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        // 点击图标要启动的activity
        shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
        // 快捷方式的图标
        ShortcutIconResource iconRes = Intent.ShortcutIconResource.fromContext(context,
                R.drawable.widget_icon);
        shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconRes);
        context.sendBroadcast(shortcut);

    }

    private static long getTotalSize(PackageStats ps) {
        if (ps != null) {
            return ps.cacheSize + ps.codeSize + ps.dataSize;
        }
        return -1;
    }

    private static String TAG = "tag";
}
